﻿using System;
using System.Web;
using System.Web.Security;
using InfoSite.SiteMembership.Interface;
using InfoSite.Tools.Storage;

namespace InfoSite.SiteMembership.Service
{
	public class AccountMembershipService : IMembershipService
	{
		private readonly MembershipProvider _provider;

		public AccountMembershipService()
			: this(null)
		{
		}

		public AccountMembershipService(MembershipProvider provider)
		{
			_provider = provider ?? Membership.Provider;
		}

		public int MinPasswordLength
		{
			get
			{
				return _provider.MinRequiredPasswordLength;
			}
		}

		public bool IsAuthorizedRequest
		{
			get { return HttpContext.Current.Request.IsAuthenticated && SessionHelper.ActiveUser != null; }
		}

		public bool ValidateUser(string userName, string password)
		{
			if (String.IsNullOrEmpty(userName)) throw new ArgumentException(ResMembership.resValueCannotBeEmpty, "userName");
			if (String.IsNullOrEmpty(password)) throw new ArgumentException(ResMembership.resValueCannotBeEmpty, "password");

			return _provider.ValidateUser(userName, password);
		}

		public MembershipUser CreateUser(string email, string password, bool isApproved, out MembershipCreateStatus status)
		{
			if (String.IsNullOrEmpty(email)) throw new ArgumentException(ResMembership.resValueCannotBeEmpty, "email");
			if (String.IsNullOrEmpty(password)) throw new ArgumentException(ResMembership.resValueCannotBeEmpty, "password");

			return _provider.CreateUser(email, password, email, null, null, isApproved, null, out status);
		}

		public void DeleteUser(string email)
		{
			_provider.DeleteUser(email, false);
		}

		public string ResetPassword(string email)
		{
			if (String.IsNullOrEmpty(email)) throw new ArgumentException(ResMembership.resValueCannotBeEmpty, "email");

			try
			{
				return _provider.ResetPassword(email, String.Empty);
			}
			catch (Exception)
			{
				throw new Exception();
			}
		}

		public bool ChangePassword(string email, string oldPassword, string newPassword)
		{
			if (String.IsNullOrEmpty(email)) throw new ArgumentException(ResMembership.resValueCannotBeEmpty, "email");
			if (String.IsNullOrEmpty(oldPassword)) throw new ArgumentException(ResMembership.resValueCannotBeEmpty, "oldPassword");
			if (String.IsNullOrEmpty(newPassword)) throw new ArgumentException(ResMembership.resValueCannotBeEmpty, "newPassword");

			// The underlying ChangePassword() will throw an exception rather
			// than return false in certain failure scenarios.
			try
			{
				MembershipUser currentUser = _provider.GetUser(email, true /* user is online */);
				return currentUser != null && _provider.ChangePassword(email, oldPassword, newPassword);
			}
			catch (ArgumentException)
			{
				return false;
			}
			catch (MembershipPasswordException)
			{
				return false;
			}
		}

		public string GeneratePassword(int length, int numberOfNonAlphanumericCharacters)
		{
			return Membership.GeneratePassword(length, numberOfNonAlphanumericCharacters);
		}
	}
}
